home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Unix / satan-1.1.1 / perl / services.pl < prev    next >
Text File  |  1995-04-10  |  4KB  |  169 lines

  1. #
  2. # infer_services - classify host by services used and provided. Output to: 
  3. #
  4. # $servers{service}{host}, $clients{service}{host}: Service is, for
  5. # example, "anonymous FTP". The servers (clients) table holds per service
  6. # and host, all SATAN records on that topic.
  7. #
  8. # $server_counts{service}, $client_counts{service}: host counts of the
  9. # corresponding entries in $servers and $clients.
  10. #
  11. # $server_severities{service}, $client_severities{service}: ditto, with
  12. # at least one vulnerability.
  13. #
  14. # $server_info{host}: newline-delimited list of services provided per host.
  15. # $client_info{host}: newline-delimited list of services consumed per host.
  16. #
  17. # $service_flag: reset whenever the tables are updated. To recalculate,
  18. # invoke make_service_info().
  19. #
  20. # Standalone usage: perl services.pl [satan_record_files...]
  21.  
  22. $services_files = "rules/services";
  23.  
  24. sub build_infer_services {
  25.     local($files) = @_;
  26.     local($service, $code, $file, $cond, $class, $host);
  27.  
  28.     $code = "sub infer_services {\n";
  29.     $code .= "\tlocal(\$type);\n";
  30.  
  31.     foreach $file (split(/\s+/, $files)) {
  32.     open(RULES, $file) || die "cannot open $file: $!";
  33.     while (<RULES>) {
  34.         chop;
  35.         while (/\\$/) {
  36.         chop;
  37.         $_ .= <RULES>;
  38.         chop;
  39.         }
  40.         s/#.*$//;
  41.         s/\s+$//;
  42.         next if /^$/;
  43.         if (/^(servers|clients)/i) {
  44.         ($class = $1) =~ tr /A-Z/a-z/;
  45.         } else {
  46.         s/@/\\@/g;
  47.         ($cond, $type, $host) = split(/\t+/, $_, 3);
  48.         die "missing service name" if $type eq "";
  49.         $host = "\$target" if $host eq "";
  50.         $code .= "\
  51.     if ($cond) {
  52.         \$$class\{\"$type\"}{$host} .= \$_ . \"\\n\";
  53.         \$service_flag = 0;
  54.     }
  55. ";
  56.         # %{${$class}{$type}} = ();
  57.         }
  58.     }
  59.     close(RULES);
  60.     }
  61.     $code .= "}\n";
  62.     return $code;
  63. }
  64.  
  65. #
  66. # Generate services-dependent statistics.
  67. #
  68. sub make_service_info {
  69.     local($service, $host, %junk);
  70.  
  71.     if ($service_flag > 0) {
  72.     return;
  73.     }
  74.     $service_flag = time();
  75.     &make_severity_info();
  76.  
  77.     print "Rebuild service type statistics...\n" if $debug;
  78.  
  79.     %server_info = ();
  80.     for $service (keys %servers) {
  81.     %junk = %{$servers{$service}};
  82.     $server_counts{$service} = sizeof(*junk);
  83.     $server_severities{$service} = 0;
  84.     for $host (keys %junk) {
  85.         $server_info{$host} .= $service . "\n";
  86.         if (exists($severity_host_type_info{$host})) {
  87.         $server_severities{$service}++;
  88.         }
  89.     }
  90.     }
  91.     %client_info = ();
  92.     for $service (keys %clients) {
  93.     %junk = %{$clients{$service}};
  94.     $client_counts{$service} = sizeof(*junk);
  95.     $client_severities{$service} = 0;
  96.     for $host (keys %junk) {
  97.         $client_info{$host} .= $service . "\n";
  98.         if (exists($severity_host_type_info{$host})) {
  99.         $client_severities{$service}++;
  100.         }
  101.     }
  102.     }
  103. }
  104.  
  105. #
  106. # Reset the service information tables.
  107. #
  108. sub clear_service_info {
  109.     %servers = ();
  110.     %clients = ();
  111.     %server_severities = ();
  112.     %client_severities = ();
  113.     %server_info = ();
  114.     %client_info = ();
  115.     $service_flag = 0;
  116. }
  117.  
  118. #
  119. # Some scaffolding for stand-alone operation
  120. #
  121. if ($running_under_satan) {
  122.     eval &build_infer_services($services_files);
  123.     die "error in $services_files: $@" if $@;
  124. } else {
  125.     $running_under_satan = -1;
  126.     $debug = 1;
  127.  
  128.     require 'perl/misc.pl';
  129.  
  130.     #
  131.     # Generate code from rules files.
  132.     #
  133.     $code = &build_infer_services($services_files);
  134.     print "Code generated from $services_files:\n\n";
  135.     print $code;
  136.     eval $code; 
  137.     die "error in $services_files: $@" if $@;
  138.  
  139.     #
  140.     # Apply rules.
  141.     #
  142.     print "\nApplying rules to all SATAN records...\n";
  143.     while (<>) {
  144.     chop;
  145.     if (&satan_split($_) == 0) {
  146.         &infer_services(_);
  147.     }
  148.     }
  149.     &make_service_info();
  150.  
  151.     print "Servers\n";
  152.     for $service (sort keys %servers) {
  153.        print "\t$service ($server_counts{$service})\n";
  154.     for (sort keys %{$servers{$service}}) {
  155.         print "\t\t$_\n";
  156.     }
  157.     }
  158.     print "Clients\n";
  159.     for $service (sort keys %clients) {
  160.        print "\t$service ($client_counts{$service})\n";
  161.     for (sort keys %{$clients{$service}}) {
  162.         print "\t\t$_\n";
  163.     }
  164.     }
  165. }
  166.  
  167. 1;
  168.